﻿<?php
/*
+--------------------------------------------------------------------------
|   phpBIZbiz v3.0 full version
|   ========================================
|   by taft@wjl.cn
|   http://www.phpbiz.cn
|   all rights reserved
+---------------------------------------------------------------------------
|
|   > 
|   > 最后修改日期：2005-9-9
|   > 
|
+--------------------------------------------------------------------------
*/
!function_exists('do_login') && exit('Forbidden');
$idx = new sql;
class sql
{
	var $mysql_version   = "";
	var $true_version    = "";
	var $PW;
	
	function sql()
	{
		
		global $DB,$INCOME,$ADMINER,$ADMIN;
		
		$this -> PW = "biz_";
		//---------------------------------------
		// Get the mySQL version.
		// Adapted from phpMyAdmin
		//---------------------------------------
		
		$DB->db_query("SELECT VERSION() AS version");
		
		if ( ! $row = $DB->db_fetch_row() )
		{
			$DB->db_query("SHOW VARIABLES LIKE 'version'");
			$row = $DB->db_fetch_row();
		}
		
		$this->true_version = $row['version'];
		
		$no_array = explode( '.', preg_replace( "/^(.+?)[-_]?/", "\\1", $row['version']) );
		
		$one   = (!isset($no_array) || !isset($no_array[0])) ? 3  : $no_array[0];
		$two   = (!isset($no_array[1]))                      ? 21 : $no_array[1];
		$three = (!isset($no_array[2]))                      ? 0  : $no_array[2];
		
   		$this->mysql_version = (int)sprintf('%d%02d%02d', $one, $two, intval($three));
	
	    switch($INCOME['code'])
	    {
		      case 'dobakup':
				  $this -> do_bakup();
			      break;
			  case 'recover':
				  $this -> file_list();
			      break;
			  case 'delf':
				  $this -> del_file();
			      break;
			  case 'inf':
				  $this -> import_file();
			      break;
			  case 'repair':
				  $this -> repair_form();
			      break;
			  case 'dorepair':
				  $this -> do_repair();
			      break;
			  case 'cache':
				  $this -> do_cache();
			      break;
		      default:
			  $this -> list_table();
		
	    }
	}

	function list_table()
	{
		
		global $ADMIN,$SKIN,$CONF,$DB;

	
		if ( $this->mysql_version < 32322 )
		{
			$extra = "<br><b>注意：你的mySQL版本缺乏一些特性功能因此一些工具被移除</b>";
		}
	
		$ADMIN->page_instruction = "这个区域允许你管理你的mySQL数据库".$extra."";
		$ADMIN->page_title  = "mySQL ".$this->true_version." 工具箱";

		$ADMIN->html .= "
				     <script language='Javascript'>
                     <!--
                     function CheckAll(cb) {
                         var fmobj = document.theForm;
                         for (var i=0;i<fmobj.elements.length;i++) {
                             var e = fmobj.elements[i];
                             if ((e.name != 'allbox') && (e.type=='checkbox') && (!e.disabled)) {
                                 e.checked = fmobj.allbox.checked;
                             }
                         }
                     }
                     function CheckCheckAll(cb) {	
                         var fmobj = document.theForm;
                         var TotalBoxes = 0;
                         var TotalOn = 0;
                         for (var i=0;i<fmobj.elements.length;i++) {
                             var e = fmobj.elements[i];
                             if ((e.name != 'allbox') && (e.type=='checkbox')) {
                                 TotalBoxes++;
                                 if (e.checked) {
                                     TotalOn++;
                                 }
                             }
                         }
                         if (TotalBoxes==TotalOn) {fmobj.allbox.checked=true;}
                         else {fmobj.allbox.checked=false;}
                     }
                     //-->
                     </script>
                     ";

		$DB->db_query("SHOW TABLE STATUS FROM `".$CONF['sql_db']."`");
			
		if ( $this->mysql_version >= 32303 )
		{
		     $ADMIN->html .= $SKIN->form_head( "theForm" );
			 $ADMIN->html .= $SKIN->form_input("code","dobakup","hidden");
			 
			 $SKIN->td_header[] = array( "数据表"      , "20%" );
     		 $SKIN->td_header[] = array( "记录"       , "10%" );
	    	 $SKIN->td_header[] = array( "大小"   , "20%" );
		     $SKIN->td_header[] = array( "索引大小" , "20%" );
			 $SKIN->td_header[] = array( '<input name="allbox" type="checkbox" value="Check All" onClick="CheckAll();">'     , "10%" );

			 $ADMIN->html .= $SKIN->table_head( "BIZ数据表" );

			 while ( $r = $DB->db_fetch_row() )
		     {
				// Check to ensure it's a table for this install...
				
				if ( ! preg_match( "/^".$CONF['sql_tbl_prefix']."/", $r['Name'] ) )
				{
					continue;
				}
				
				$idx_size += $r['Index_length'];
				$tbl_size += $r['Data_length'];
				
				$iBit = ($r['Index_length'] > 0) ? 1 : 0;
				$tBit = ($r['Data_length'] > 0)  ? 1 : 0;
				
				$idx = $this->gen_size( $r['Index_length'], 3, $iBit );
				$tbl = $this->gen_size( $r['Data_length'] , 3, $tBit );
				
				$ADMIN->html .= $SKIN->table_row( array( "<b><span style='font-size:12px'>tbl_{$r['Name']}</span></b>",
														  "<center>{$r['Rows']}</center>",
														  "<div align='right'><span style='color:blue;font-size:12px'>{$tbl[0]} {$tbl[1]}</span></div>",
														  "<div align='right'>{$idx[0]} {$idx[1]}</div>",
														  "<center><input name=\"{$r['Name']}\" value=1 type='checkbox' onClick=\"CheckCheckAll();\"></center>",
												 )      );
			}
			
			$total = $idx_size + $tbl_size;
			
			$iBit = ($idx_size > 0) ? 1 : 0;
			$tBit = ($tbl_size > 0)  ? 1 : 0;
			$oBit = ($total    > 0)  ? 1 : 0;
			
			$idx = $this->gen_size( $idx_size , 3, $iBit );
			$tbl = $this->gen_size( $tbl_size , 3, $tBit );
			$tot = $this->gen_size( $total    , 3, $oBit );
			
			$ADMIN->html .= $SKIN->table_row( array ("&nbsp;",
													  "&nbsp;",
													  "<div align='right'><b>{$tbl[0]} {$tbl[1]}</b></div>",
													  "<div align='right'><b>{$idx[0]} {$idx[1]}</b></div>",
													  "<div align='right'>总计 (<b>{$tot[0]} {$tot[1]}</b>)</div>",
											 )       );
											 
		}
		else
		{
			// display a basic information table

			$ADMIN ->html .= $SKIN -> form_head("theForm");
			$ADMIN->html .= $SKIN->form_input("code","dobakup","hidden");

			$SKIN->td_header[] = array( "数据表"      , "60%" );
			$SKIN->td_header[] = array( "行"       , "30%" );
			$SKIN->td_header[] = array( '<input name="allbox" type="checkbox" value="Check All" onClick="CheckAll();">'     , "10%" );
			
			$ADMIN->html .= $SKIN->table_head( "BIZ数据表" );
			
			$tables = $DB->get_table_names();
			
			foreach($tables as $tbl)
			{
				// Ensure that we're only peeking at IBF tables
				
				if ( ! preg_match( "/^".$CONF['sql_tbl_prefix']."/", $tbl ) )
				{
					continue;
				}
				
				$DB->db_query("SELECT COUNT(*) AS Rows FROM $tbl");
				
				$cnt = $DB->db_fetch_row();
				
				$ADMIN->html .= $SKIN->table_row( array( "<b><span style='font-size:12px'>$tbl</span></b>",
														  "<center>{$cnt['Rows']}</center>",
														  "<center><input name='$tbl' type='checkbox' onClick=\"CheckCheckAll(this);\"></center>",
												 )      );
												 
			}
			
		}
		$ADMIN -> html .= $SKIN -> form_end("备分");
		$ADMIN->html .= $SKIN->table_end();
        
		$ADMIN->output();
	
	}

	function file_list()
	{
		global $CONF,$ADMIN,$SKIN;


 
		$handle=opendir($CONF['bakup_dir']);
	    
		while(false!== ($file = readdir($handle)))
		{
		    
			if(  strstr($file,$this -> PW)  && eregi("\.sql$",$file))
			{
				
				$file_time = substr( $file, -14,10);
				$file_array[]=array( $file, $file_time);
		     
            }
	   }

	   $ADMIN -> page_title ="恢复备份文件";
	   $ADMIN -> page_instruction ="点击‘导入’恢复备分数据文件到数据库，点击‘移除’直接删除数据备分文件";

	   $SKIN ->td_header[] = array("文件名","40%");
       $SKIN ->td_header[] = array("备份时间","30%");
	   $SKIN ->td_header[] = array("导入","15%");
	   $SKIN ->td_header[] = array("移除","15%");

	   $ADMIN ->html .= $SKIN -> table_head("备份文件列表");
	   
	   if( !is_array($file_array) ) 
	   {
		   $ADMIN -> html .= $SKIN -> td_basic("目前没有备份文件，请点<a href='admin.php?act=sql'><b>这里</b></a>备份","center");
	   }else
	   {
	       foreach( $file_array as $k => $v )
	       {
              $ADMIN -> html .= $SKIN ->table_row( array("<center><b>{$file_array[$k][0]}</b></center>","<center>".date("Y-m-d H:i:s", "{$file_array[$k][1]}")."</center>","<center><a href='admin.php?act=sql&code=inf&file={$file_array[$k][0]}'>导入</a></center>","<center><a href='admin.php?act=sql&code=delf&file={$file_array[$k][0]}'>移除</a></center>") );
	       }
	   }

	   $ADMIN -> html .= $SKIN -> table_end();

	   $ADMIN -> output();

	}
    function repair_form()
	{
		global $ADMIN,$SKIN,$DB,$CONF;

		if ( $this->mysql_version < 32322 )
		{
			$extra = "<br><b>注意：你的mySQL版本缺乏一些特性功能因此一些工具被移除</b>";
		}

		$ADMIN->page_instruction = "这个区域允许你管理你的mySQL数据库".$extra."";
		$ADMIN->page_title  = "mySQL ".$this->true_version." 工具箱";

		$ADMIN->html .= "
				     <script language='Javascript'>
                     <!--
                     function CheckAll(cb) {
                         var fmobj = document.theForm;
                         for (var i=0;i<fmobj.elements.length;i++) {
                             var e = fmobj.elements[i];
                             if ((e.name != 'allbox') && (e.type=='checkbox') && (!e.disabled)) {
                                 e.checked = fmobj.allbox.checked;
                             }
                         }
                     }
                     function CheckCheckAll(cb) {	
                         var fmobj = document.theForm;
                         var TotalBoxes = 0;
                         var TotalOn = 0;
                         for (var i=0;i<fmobj.elements.length;i++) {
                             var e = fmobj.elements[i];
                             if ((e.name != 'allbox') && (e.type=='checkbox')) {
                                 TotalBoxes++;
                                 if (e.checked) {
                                     TotalOn++;
                                 }
                             }
                         }
                         if (TotalBoxes==TotalOn) {fmobj.allbox.checked=true;}
                         else {fmobj.allbox.checked=false;}
                     }
                     //-->
                     </script>
                     ";

		$DB->db_query("SHOW TABLE STATUS FROM `".$CONF['sql_db']."`");
			
		if ( $this->mysql_version >= 32303 )
		{
		     $ADMIN->html .= $SKIN->form_head( "theForm" );
			 $ADMIN->html .= $SKIN->form_input("code","dorepair","hidden");
			 
			 $SKIN->td_header[] = array( "数据表"      , "20%" );
     		 $SKIN->td_header[] = array( "记录"       , "10%" );
	    	 $SKIN->td_header[] = array( "大小"   , "20%" );
		     $SKIN->td_header[] = array( "索引大小" , "20%" );
			 $SKIN->td_header[] = array( '<input name="allbox" type="checkbox" value="Check All" onClick="CheckAll();">'     , "10%" );

			 $ADMIN->html .= $SKIN->table_head( "BIZ数据表" );

			 while ( $r = $DB->db_fetch_row() )
		     {
				// Check to ensure it's a table for this install...
				
				if ( ! preg_match( "/^".$CONF['sql_tbl_prefix']."/", $r['Name'] ) )
				{
					continue;
				}
				
				$idx_size += $r['Index_length'];
				$tbl_size += $r['Data_length'];
				
				$iBit = ($r['Index_length'] > 0) ? 1 : 0;
				$tBit = ($r['Data_length'] > 0)  ? 1 : 0;
				
				$idx = $this->gen_size( $r['Index_length'], 3, $iBit );
				$tbl = $this->gen_size( $r['Data_length'] , 3, $tBit );
				
				$ADMIN->html .= $SKIN->table_row( array( "<b><span style='font-size:12px'>tbl_{$r['Name']}</span></b>",
														  "<center>{$r['Rows']}</center>",
														  "<div align='right'><span style='color:blue;font-size:12px'>{$tbl[0]} {$tbl[1]}</span></div>",
														  "<div align='right'>{$idx[0]} {$idx[1]}</div>",
														  "<center><input name=\"{$r['Name']}\" value=1 type='checkbox' onClick=\"CheckCheckAll();\"></center>",
												 )      );
			}
			
			$total = $idx_size + $tbl_size;
			
			$iBit = ($idx_size > 0) ? 1 : 0;
			$tBit = ($tbl_size > 0)  ? 1 : 0;
			$oBit = ($total    > 0)  ? 1 : 0;
			
			$idx = $this->gen_size( $idx_size , 3, $iBit );
			$tbl = $this->gen_size( $tbl_size , 3, $tBit );
			$tot = $this->gen_size( $total    , 3, $oBit );
			
			$ADMIN->html .= $SKIN->table_row( array ("&nbsp;",
													  "&nbsp;",
													  "<div align='right'><b>{$tbl[0]} {$tbl[1]}</b></div>",
													  "<div align='right'><b>{$idx[0]} {$idx[1]}</b></div>",
													  "<div align='right'>总计 (<b>{$tot[0]} {$tot[1]}</b>)</div>",
											 )       );
											 
		}
		else
		{
			// display a basic information table

			$ADMIN ->html .= $SKIN -> form_head("theForm");
			$ADMIN->html .= $SKIN->form_input("code","dobakup","hidden");

			$SKIN->td_header[] = array( "数据表"      , "60%" );
			$SKIN->td_header[] = array( "行"       , "30%" );
			$SKIN->td_header[] = array( '<input name="allbox" type="checkbox" value="Check All" onClick="CheckAll();">'     , "10%" );
			
			$ADMIN->html .= $SKIN->table_head( "BIZ数据表" );
			
			$tables = $DB->get_table_names();
			
			foreach($tables as $tbl)
			{
				// Ensure that we're only peeking at IBF tables
				
				if ( ! preg_match( "/^".$CONF['sql_tbl_prefix']."/", $tbl ) )
				{
					continue;
				}
				
				$DB->db_query("SELECT COUNT(*) AS Rows FROM $tbl");
				
				$cnt = $DB->db_fetch_row();
				
				$ADMIN->html .= $SKIN->table_row( array( "<b><span style='font-size:12px'>$tbl</span></b>",
														  "<center>{$cnt['Rows']}</center>",
														  "<center><input name='$tbl' type='checkbox' onClick=\"CheckCheckAll(this);\"></center>",
												 )      );
												 
			}
			
		}

		//----------------------------
		// Add in the bottom stuff
		//----------------------------
											 
		if ( $this->mysql_version < 32322 )
		{
			$ADMIN->html .= $SKIN->td_basic( "<select id='button' name='tool'>
													<option value='optimize'>优化选择的数据表</option>
												  </select>
												 <input type='submit' value='Go!' id='button'></form>", "center", "tdrow2" );
		}
		else
		{
										 
			$ADMIN->html .= $SKIN->td_basic( "<select id='button' name='tool'>
													<option value='optimize'>优化选择的数据表</option>
													<option value='repair'>修复选择的数据表</option>
													<option value='check'>检查选择的数据表</option>
													<option value='analyze'>分析选择的数据表</option>
												  </select>
												 <input type='submit' value='Go!' id='button'></form>", "center", "tdrow2" );
		}
		$ADMIN -> html .= $SKIN -> form_end("");
		$ADMIN->html .= $SKIN->table_end();
        
		$ADMIN->output();

	}

	function del_file()
	{
		global $INCOME,$ADMIN,$CONF;

		if( !is_file( $CONF['bakup_dir'].$INCOME['file'] ) ) 
		{
			$ADMIN -> error( "文件查询错误！" );
		}
		
		if( strstr( $INCOME['file'],$this -> PW )  && eregi("\.sql$",$INCOME['file'] ) )
		{ 
			@unlink( $CONF['bakup_dir'].$INCOME['file'] );
		}
		else
		{
			$ADMIN -> error( "文件查询错误！" );
		}

		
		$ADMIN -> record_log("删除备份数据文件‘{$INCOME['file']}’");
		$ADMIN -> done_screen( "数据备份", "数据恢复", "act=sql&code=recover" );
	}

	function import_file()
	{
		global $INCOME,$ADMIN,$CONF;

		if( !is_file( $CONF['bakup_dir'].$INCOME['file'] ) ) 
		{
			$ADMIN -> error( "文件查询错误！" );
		}
		
		if( strstr( $INCOME['file'],$this -> PW )  && eregi("\.sql$",$INCOME['file'] ) )
		{ 
			$sql = $this -> read_file( $CONF['bakup_dir'].$INCOME['file'] );
		
		    $this -> write_data( $sql );
		}
		else
		{
			$ADMIN -> error( "文件查询错误！" );
		}
		
		$ADMIN -> record_log("恢复备份数据文件‘{$INCOME['file']}’");
		$ADMIN -> done_screen( "数据备份", "数据恢复", "act=sql&code=recover" );

	}

	function do_repair()
	{
		global $INCOME, $CONF, $DB, $SKIN, $ADMIN;
		
		$tb = array();

		foreach( $INCOME as $k => $v )
		{
            
			 strstr( $k,$CONF['sql_tbl_prefix'] ) && $INCOME[$k] && $tb[] = $k ;
		}

		if( count($tb)<1 ) $ADMIN -> error("请选择你需要维护的表格！");

		if (strtoupper($INCOME['tool']) == 'DROP' || strtoupper($INCOME['tool']) == 'CREATE' || strtoupper($INCOME['tool']) == 'FLUSH')
		{
			$ADMIN->error("你不能做这些，对不起");
		}

		foreach($tb as $table)
		{
			$DB->db_query(strtoupper($INCOME['tool'])." TABLE $table" );
			
			$fields = $DB->get_result_fields();
			
			$data = $DB->db_fetch_row();
			
			$cnt = count($fields);
			
			// Print the headers - we don't what or how many so...
			
			for( $i = 0; $i < $cnt; $i++ )
			{
				$SKIN->td_header[] = array( $fields[$i]->name , "*" );
			}
			
			$ADMIN->html .= $SKIN->table_head( "结果： ".$IN['tool']." ".$table );
			
			// Grab the rows - we don't what or how many so...
			
			$rows = array();
			
			for( $i = 0; $i < $cnt; $i++ )
			{
				$rows[] = $data[ $fields[$i]->name ];
			}
			
			$ADMIN->html .= $SKIN->table_row( $rows );
			
			$ADMIN->html .= $SKIN->table_end();
		}
		
		//+-------------------------------
		
		$ADMIN->output();
  
	}

	function do_bakup()
	{
		global $ADMIN,$INCOME,$CONF;
       
		$tb = array();

		foreach( $INCOME as $k => $v )
		{
            
			 strstr( $k,$CONF['sql_tbl_prefix'] ) && $INCOME[$k] && $tb[] = $k ;
		}

		if( count($tb)<1 ) $ADMIN -> error("请选择你需要备份的表格！");

		$t = $this -> bakup_table( $tb);
		$d = $this -> bakup_data ( $tb);
		
		$write_data = $t.$d;
		
		$filename='biz_'.date('md').'_'.time().'.sql';

		$this -> write_file( $CONF['bakup_dir'].$filename, $write_data );

		$ADMIN -> record_log("备分数据表");
		
		$ADMIN -> done_screen("数据备分", "数据备份", "act=sql&code=bakup" );

	}

	//-------------------------------------------------------------
	// Convert chars into byte sizes
	// (Based on a similar function in phpmyadmin)
	//-------------------------------------------------------------
	
	function gen_size($val, $li, $sepa )
	{
		$sep     = pow(10, $sepa);
		$li      = pow(10, $li);
		$retval  = $val;
		$unit    = 'Bytes';
	
		if ($val >= $li * 1000000)
		{
			$val = round( $val / (1073741824/$sep) ) / $sep;
			$unit  = 'GB';
		}
		else if ($val >= $li*1000)
		{
			$val = round( $val / (1048576/$sep) ) / $sep;
			$unit  = 'MB';
		}
		else if ($val >= $li)
		{
			$val = round( $val / (1024/$sep) ) / $sep;
			$unit  = 'KB';
		}
		if ($unit != 'Bytes')
		{
			$retval = number_format($val, $sepa, '.', ',');
		}
		else
		{
			$retval = number_format($val, 0, '.', ',');
		}
		
		return array($retval, $unit);
    }

	function bakup_data( $tabledb )
	{
		global $DB;
		
		$t_count=count($tabledb);
	
		for( $i=0; $i<$t_count; $i++ )
		{

			$query = $DB->db_query("SELECT * FROM ".$tabledb[$i] );

			!$start && $rows=$DB-> db_fetch_num( $query );
			
			$num_F =  mysql_num_fields( $query );

			while ( $datadb = mysql_fetch_row($query) )
			{
				$start++;
				$bakup_data .= "INSERT INTO $tabledb[$i] VALUES("."'".mysql_escape_string($datadb[0])."'";
				$tempdb='';
				for($j=1;$j<$num_F;$j++)
				{
				$tempdb.=",'".mysql_escape_string($datadb[$j])."'";
				}
			
			    $bakup_data .=$tempdb. ");\n";
			   if($sizelimit && strlen($bakup_data)>$sizelimit*1000)     break;
			   
		     }

		    $bakup_data .="\n";

		    $start=0;
	    }
	    

	   return $bakup_data;
    }

	function bakup_table($tabledb)
	{
	    global $DB;
	      
		foreach($tabledb as $table)
		{
			$creat_table_str.= "DROP TABLE IF EXISTS $table;\n";
			$DB->db_query( "SHOW CREATE TABLE $table" );
			$creat_table = $DB -> db_fetch_row();
			$creat_table['Create Table']=str_replace($creat_table['Table'],$table,$creat_table['Create Table']);
			$creat_table_str.=$creat_table['Create Table'].";\n\n";
	    }
	    return $creat_table_str;
    }

	function write_file($file_name,$data,$method="rb+",$iflock=1)
	{
		touch($file_name);
		
		$handle=fopen($file_name,$method);
		
		if($iflock)
		{
			flock($handle,LOCK_EX);
		}
		
		fputs($handle,$data);
		
		if($method=="rb+") ftruncate($handle,strlen($data));
		
		fclose($handle);
	}
	
	function read_file($file_name,$method="rb")
	{
	    if($handle=@fopen($file_name,$method))
		{
			flock($handle,LOCK_SH);
			$filedata=fread($handle,filesize($file_name));
			fclose($handle);
		}
		return $filedata;
	}

	function write_data($sql) 
	{
		global $DB;
		
		$sql=str_replace("\r",'\n',$sql);
	    
		$sql_array=explode(";\n",$sql);
	    
		foreach($sql_array as $query)
		{
		    $query=trim($query);
		    
			if($query[0]=='#')
			{
			    $queryy=explode("\n",$query);
			    $query='';
			    
				foreach( $queryy as $value )
				{
				     if($value[0]!='#')
					 {
					    $query.=$value;
				     }
			    }
		    }
		    
			if( $query )
			{
			    $query=trim(str_replace("\n",'',$query));
				$DB -> db_query($query);
		    }
	    }
	}
	function do_cache()
	{
		global $ADMIN,$CONF;
		@unlink("cache/index_cache.php");
		//TODO add cat cache file
		@unlink(ROOT_PATH."cache/cat_cache.php");
	
		require ROOT_PATH."source/libs/smarty/Smarty.class.php";
		$admin_smarty = new Smarty();
		$sk = $CONF[template]?$CONF[template]:"skin1";
		$admin_smarty-> template_dir = "./templates/".$sk; 
        $admin_smarty -> config_dir = $admin_smarty -> template_dir;
		$admin_smarty -> clear_all_cache();
		$admin_smarty -> clear_compiled_tpl();
		
		$level_cache = new cache;
		$level_cache -> cache_level();
		$level_cache -> cache_fee();

		$ADMIN -> record_log("重建数据缓存");
		$ADMIN -> done_screen("重建数据缓存成功", "数据库管理", "act=sql&code=bakup" );
	}

}
?>